package jiang.jredis.starter;

import jiang.jredis.cache.CacheExpireAspect;
import jiang.jredis.cache.JRedisCacheManager;
import jiang.jredis.starter.annotation.EnableDoubleCaching;
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.RedisTemplate;

import java.util.Stack;

/**
 * RedisCache相关配置
 * 只有添加了@EnableCaching注解才生效
 * 1.缓存过期时间存储栈
 * 2.缓存失效时间代理切面
 * 3.JRedisCacheManager（如果添加了@EnableDoubleCaching则不生效）
 */
@Configuration
@ConditionalOnBean(annotation = EnableCaching.class)
public class RedisCacheAutoConfiguration {

    /**
     * 获取应用名配置信息
     */
    @Value("${spring.application.name}")
    private String applicationName;

    /**
     * 缓存过期时间存储栈 ThreadLocal
     * 用于存放缓存过期时间
     */
    @Bean
    public ThreadLocal<Stack<Long>> cacheExpireStackThreadLocal() {
        return ThreadLocal.withInitial(Stack::new);
    }

    /**
     * 设置缓存失效时间代理切面
     * 需要注入缓存过期时间存储栈来存储过期时间
     */
    @Bean
    public CacheExpireAspect cacheExpireAspect(ThreadLocal<Stack<Long>> cacheExpireStackThreadLocal) {
        return new CacheExpireAspect(cacheExpireStackThreadLocal);
    }

    /**
     * 注入JRedisCacheManager
     * 如果添加了@EnableDoubleCaching则不生效
     */
    @Bean
    @ConditionalOnMissingBean(annotation = EnableDoubleCaching.class)
    public CacheManager cacheManager(RedisTemplate<String,Object> redisTemplate, RedissonClient redissonClient,
                                     ThreadLocal<Stack<Long>> cacheExpireStackThreadLocal) {
        return new JRedisCacheManager(applicationName, redisTemplate, (Redisson) redissonClient, cacheExpireStackThreadLocal);
    }

}
